#include <SDL/SDL.h>
#include <stdio.h>
#include <string.h>
#include "malloc.h"

#include "pantalla.h"
#include "personaje.h"
#include "tiempo.h"
#include "escenario.h"
#include "scroll.h"
#include "particulas.h"
#include "texto.h"
#include "dibujo2D.h"
#include "disparo.h"
#include "lista.h"
#include "recursos.h"
#include "jugador.h"
#include "enemigo.h"
#include "control.h"
#include "objetos.h"
#include "editor.h"

/*--------------------------
	EstadoPrograma
---------------------------*/
typedef enum 
{
	EST_PORTADA,
	EST_JUGANDO,
	EST_FINJUEGO,
	EST_LIBERARJUEGO,
	EST_CARGARPORTADA,
	EST_CARGARJUEGO
} EstadoPrograma;


/*------------------------------------------------------------------------------
	Loading screen
------------------------------------------------------------------------------*/
void Cargando()
{
	CTextura t;
	t.Cargar("demoport.png",PATH_DATA);

	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	glPushMatrix(); 
	glLoadIdentity();
	glDisable( GL_DEPTH_TEST );	

	t.Bind();	
    glBegin( GL_QUADS );
    	glTexCoord2f(0,1); 
   		glVertex3f(-1,-1,0);
      		
   		glTexCoord2f(1,1);      		
   		glVertex3f(1,-1,0);      
      		
   		glTexCoord2f(1,0); 
   		glVertex3f(1,1,0);            		

    	glTexCoord2f(0,0); 
   		glVertex3f(-1,1,0);
   	glEnd( );

    glEnable( GL_DEPTH_TEST );

    glPopMatrix(); 
    t.Liberar();
    SDL_GL_SwapBuffers();    
}

/*------------------------------------------------------------------------------
	MAIN PROGRAM
------------------------------------------------------------------------------*/
int main(int argc,char *argv[])
{	
	
	EstadoPrograma estado=EST_CARGARPORTADA;	

	SDL_Event 	event;
	CPantalla 	pantalla;	
	CTiempo		tiempo;	
	CEscenario	escenario;
	
	CScroll		scroll;
	CTexto 		texto;
	CDibujo2D	portada;
	CDibujo2D	portadafin;	
	
	CLista<CEnemigo *> listaP;
	CLista<CDisparo *> lista_disparos;
	CLista<CDisparo *> lista_disparosEnemigos;
	CLista<CParticulas *> lista_efectos;	
	CObjetos objetos;
	
	CRecursos	recursos;
	CJugador	PJ_1;
	CEnemigo	*enemigo;
	Control 	controlP1;
		
	
	printf("> INICIO\n");
	printf("----------\n");
	
	if(! (pantalla.Inicializar(ANCHO,ALTO,PANTALLA_COMPLETA,"Unfinished!")))
	{
		pantalla.Liberar();
		return 0;
	}

/*

	CEditor editor;				
	if(!editor.Inicializar(&pantalla))
	{
		editor.Liberar();
		return 1;
	}
		
	editor.Editar();
	editor.Liberar();
	//return 1;
*/
	Cargando();

	/***************************************************************************
		CARGAMOS LOS RECURSOS
	***************************************************************************/	
		
	Bool fin=FALSE;
	Bool isActive=TRUE;
	Bool pulsado=FALSE;
	Bool finjuego = FALSE;
	int vidas=3;

	/***************************************************************************
		BUCLE DE JUEGO
	***************************************************************************/
	
	
	
	float arr[3]={0.11,0.7,0.25};
	float aba[3]={0.11,0.38,0.24};

	while ( !fin )
	{	
		switch(estado)
		{		
			
			//------------------------------------------------------------------
			case EST_CARGARPORTADA:
				portada.Iniciar("data/demoport.png");
				portadafin.Iniciar("data/endp.png");
				estado=EST_PORTADA;
			break;
			//------------------------------------------------------------------
			case EST_CARGARJUEGO:
				SDLKey teclas[NUM_TECLAS];
			/*	teclas[ARRIBA]=		SDLK_w;
				teclas[ABAJO]=		SDLK_s;
				teclas[IZQUIERDA]=	SDLK_a;
				teclas[DERECHA]=	SDLK_d;
				teclas[DISPARO]=	SDLK_h;
				teclas[SALTO]=		SDLK_j;
			*/

				teclas[ARRIBA]=		SDLK_UP;
				teclas[ABAJO]=		SDLK_DOWN;
				teclas[IZQUIERDA]=	SDLK_LEFT;
				teclas[DERECHA]=	SDLK_RIGHT;
				teclas[DISPARO]=	SDLK_SPACE;
				teclas[SALTO]=		SDLK_LALT;
					
				controlP1.Inicializar(teclas);
				
				recursos.Cargar();
				
				objetos.Iniciar(&recursos);


				scroll.Iniciar (0,recursos.getTexturaScroll(0),&pantalla,FALSE,0.002);	
				scroll.Iniciar (1,recursos.getTexturaScroll(2),&pantalla,FALSE,0.001,0,0.75);
				scroll.setColor(1,0.5,0.5,0.5);
				scroll.Iniciar (2,recursos.getTexturaScroll(3),&pantalla,FALSE,0.0005,0,0.60);
				scroll.setColor(2,0.25,0.25,0.25);
				scroll.Iniciar (3,recursos.getTexturaScroll(1),&pantalla,FALSE,0);
				scroll.setColor(3,0.125,0.125,0.4);	
				scroll.Iniciar (4,&pantalla,arr,aba);	

				escenario.Iniciar(&recursos);

				float escala;
				escala=0.0095;
				
				PJ_1.setModelo(recursos.getMd2PJ());
				PJ_1.setX(0.5);
				PJ_1.setY(0);
				PJ_1.setZ(-0.1);	
				PJ_1.setRotY(0);	
				PJ_1.setRotX(270);
				PJ_1.setRotZ(0);				
				PJ_1.setControl(&controlP1);
				PJ_1.setEscalaX(escala*5);
				PJ_1.setEscalaY(escala*5);
				PJ_1.setEscalaZ(escala*5);	
				PJ_1.setEstado(ESTADO_PJ_SALTO);
				PJ_1.setEscenario(&escenario);

				PJ_1.setRecursos(&recursos);
				PJ_1.setObjetos(&objetos);	

				PJ_1.setDelineado(TRUE);
				
				pantalla.setFollowMe(&PJ_1);
				pantalla.setEscenario(&escenario);


				for (int cont=0;cont<49;cont++)
				{
					enemigo=new CEnemigo();
					enemigo->setModelo(recursos.getMd2Enemigo(0));
					enemigo->setX(cont+2);
					enemigo->setY(-0.85);
					enemigo->setRotX(270);
					enemigo->setRotY(0);
					enemigo->setRotZ(0);
					enemigo->setDelineado(TRUE);
					enemigo->setColor(1,0.2,0.2);
					enemigo->setTransparente(TRUE);
					enemigo->setEscalaX(escala*5 );
					enemigo->setEscalaY(escala*5);
					enemigo->setEscalaZ(escala*5);	
					enemigo->setEstado(ESTADO_PJ_SALTO);
					enemigo->HacerCaer();
					enemigo->setEscenario(&escenario);
					enemigo->setListaDisparos(objetos.getListaDisparosEnemigos());
					enemigo->setRecursos(&recursos);
					enemigo->setObjetivo(&PJ_1);
					objetos.AniadirEnemigo(enemigo);
					enemigo=NULL;
				}

				enemigo=NULL;	
				
				texto.Iniciar("font.png");
				texto.setEscala(0.025);
			 					
				CParticulas *p;
				
				p=new CParticulas();
				p->setTextura(recursos.getTexturaParticula(0));
				p->Iniciar(70,PART_FUEGO,1,0.0075,0.15,-0.38,Z_0);
				p->setColor(0.25,0.05,0);
				p->setEscala(1.75);
				objetos.AniadirParticula(p);	
				p=NULL;	
				
				p=new CParticulas();
				p->setTextura(recursos.getTexturaParticula(0));
				p->Iniciar(5,PART_FUEGO,4,0.0085,0.15,-0.38,Z_0);
				p->setColor(1,0.001,0.001);
				p->setEscala(0.25);
				objetos.AniadirParticula(p);	
				p=NULL;
				
				estado=EST_JUGANDO;
			break;
			//------------------------------------------------------------------
			case EST_PORTADA:
				while ( SDL_PollEvent( &event ) )
			    {
				    switch( event.type ){
		   	   			case SDL_ACTIVEEVENT:
						    if ( event.active.gain == 0 )
								isActive = FALSE;
						    else
								isActive = TRUE;
					    break;	

						case SDL_QUIT:	
						    fin = TRUE;
					    break;
					    
					    case SDL_KEYDOWN:
							if(event.key.keysym.sym==SDLK_ESCAPE)
							    fin = TRUE;	
							
							if(event.key.keysym.sym==SDLK_KP_ENTER ||
							   event.key.keysym.sym== SDLK_RETURN)
							    pulsado = TRUE;	
							    
							    				    
					    break;
					    
						default:
					    break;
					}
				}
								
				portada.Dibujar();
				
				if(fin)
					portada.Liberar();
					
				if(pulsado)
				{
					portada.Liberar();
					estado=EST_CARGARJUEGO;
					portada.Iniciar("data/cargando.png");
					portada.Dibujar();
					portada.Liberar();
				}
			break;
			//------------------------------------------------------------------
			case EST_FINJUEGO:
				while ( SDL_PollEvent( &event ) )
			    {
				    switch( event.type ){
		   	   			case SDL_ACTIVEEVENT:
						    if ( event.active.gain == 0 )
								isActive = FALSE;
						    else
								isActive = TRUE;
					    break;	

						case SDL_QUIT:	
						    fin = TRUE;
					    break;
					    
					    case SDL_KEYDOWN:
							if(event.key.keysym.sym==SDLK_ESCAPE)
							    fin = TRUE;	
							    
							if(event.key.keysym.sym==SDLK_KP_ENTER ||
							   event.key.keysym.sym== SDLK_RETURN)
							    pulsado = TRUE;					    
					    break;

						default:
					    break;
					}
				}
								
				portadafin.Dibujar();
				
				if(fin)
					portadafin.Liberar();
					
				if(pulsado)
				{
					portadafin.Liberar();
					fin=TRUE;
				}
			break;
			//------------------------------------------------------------------
			case EST_JUGANDO:
				tiempo.Resetear();
				
				while ( SDL_PollEvent( &event ) )
			    {CDibujo2D	portada;
				    switch( event.type ){
		   	   			case SDL_ACTIVEEVENT:
						    if ( event.active.gain == 0 )
								isActive = FALSE;
						    else
								isActive = TRUE;
					    break;	

						case SDL_QUIT:	
						    fin = TRUE;
					    break;
					    
					    case SDL_KEYDOWN:
							if(event.key.keysym.sym==SDLK_ESCAPE)
							    fin = TRUE;					    
					    break;
					    
						default:
					    break;
					}
				}
					
				if (isActive)
				{			
					if(objetos.getListaEnemigos()->Vacia())
					{
						finjuego=TRUE;
					}
					
				    pantalla.Dibujar();		   
				    scroll.Dibujar();	
				      			  			
		  			PJ_1.Dibujar(); 
		  			
		  			if(!PJ_1.getVivo())
		  			{
		  				CParticulas *pt;
						pt=new CParticulas();						
						pt->setColor(PJ_1.getColorR(),PJ_1.getColorG(),PJ_1.getColorB());
						
						pt->Iniciar(75, PART_EXPLOSION,0.95,0.02,PJ_1.getX(),PJ_1.getY(),Z_0);
						
						pt->setTextura(recursos.getTexturaParticula(0));						
						pt->setEscala(6);
						objetos.AniadirParticula(pt);
						pt=NULL;
					
						pt=new CParticulas();						
						pt->setColor(PJ_1.getColorR(),PJ_1.getColorG(),PJ_1.getColorB());
						
						pt->Iniciar(20, PART_EXPLOSION,0.7,0.03,PJ_1.getX(),PJ_1.getY(),Z_0);
						
						pt->setTextura(recursos.getTexturaParticula(0));						
						pt->setEscala(6);
						objetos.AniadirParticula(pt);
						pt=NULL;
						
						pt=new CParticulas();						
						pt->setColor(PJ_1.getColorR(),PJ_1.getColorG(),PJ_1.getColorB());
						
						pt->Iniciar(30, PART_EXPLOSION,0.5,0.041,PJ_1.getX(),PJ_1.getY(),Z_0);
						
						pt->setTextura(recursos.getTexturaParticula(0));						
						pt->setEscala(6);
						objetos.AniadirParticula(pt);
						pt=NULL;
						PJ_1.setVivo(TRUE);
						
						PJ_1.setY(1.5);
						PJ_1.setEstado(ESTADO_PJ_SALTO);
						
						vidas--;
						
						if(vidas<0)
						{
							finjuego=TRUE;
						}
		  			} 			  			

					escenario.setX(pantalla.getCamX());  		    
		   		    escenario.Dibujar(); 
		  			
		  			objetos.Dibujar();
		   		    
		   		    texto.setEscala(0.025);
		   		    texto.setColor(1,1,1);
		   		    texto.Escribir(-1+0.01,-1+0.025,VERSION,ALINEACION_DERECHA);  		    
		   		    texto.Escribir(1,-1+0.015,"ADVICE: This a demo",ALINEACION_IZQUIERDA);
				    texto.Escribir(1,-1+0.080,"Directions - Move / space-Shot   Alt-Jump / ESC - Exit",ALINEACION_IZQUIERDA);
		   		    texto.setEscala(0.04);
		   		    
		   		    char texvidas[255];
		   		    texto.setColor(1,0,0);
		   		    sprintf(texvidas,"Enemies: %i",objetos.getListaEnemigos()->getNumElem());
		   		    texto.Escribir(-1+0.01,-1+0.065,texvidas,ALINEACION_DERECHA);  		    

		   		    texto.setColor(1,0,0);
		   		    sprintf(texvidas,"Lifes: %i",vidas);
		   		    texto.Escribir(-1+0.018,-1+0.125,texvidas,ALINEACION_DERECHA);		   		   	    	
				}
				
				unsigned int frametime;
				do 
				{
					frametime=tiempo.CurrentTime();
				} while (frametime<25);			
				
				if(finjuego)
				{
					pulsado=FALSE;
					estado=EST_LIBERARJUEGO;
				}	
				
				
				if(fin)
				{					
					escenario.Liberar(); 
					scroll.Liberar();	
					texto.Liberar();
					
					recursos.Liberar();
					PJ_1.Liberar();
					
					printf("LISTA_P: \n");
					listaP.Liberar();
					printf("LISTA_Disparos: \n");
					lista_disparos.Liberar();
					printf("LISTA_Disparos_Enemigos: \n");
					lista_disparosEnemigos.Liberar();
					printf("LISTA_Efectos: \n");
					lista_efectos.Liberar();
				}
				
			break;// est_jugando
			
			//------------------------------------------------------------------
			case EST_LIBERARJUEGO:
				
				escenario.Liberar(); 
				scroll.Liberar();	
				texto.Liberar();

				recursos.Liberar();
				PJ_1.Liberar();
				
				printf("LISTA_P: \n");
				listaP.Liberar();
				printf("LISTA_Disparos: \n");
				lista_disparos.Liberar();
				printf("LISTA_Disparos_Enemigos: \n");
				lista_disparosEnemigos.Liberar();
				printf("LISTA_Efectos: \n");
				lista_efectos.Liberar();
				
				
				//
				
				estado=EST_FINJUEGO;
			
			break;						
		}		
		
		pantalla.Actualizar();
	}
	
	/***************************************************************************
		LIBERAMOS LOS RECURSOS
	***************************************************************************/
	pantalla.Liberar();
	

	printf("----------\n");
	printf("> FIN\n");
	return 1;
}
